package cn.tpshion.vm.handler;

import cn.tpshion.vm.base.config.NodeConfig;
import cn.tpshion.vm.common.constant.SecretType;
import cn.tpshion.vm.common.utils.AESUtil;
import cn.tpshion.vm.common.utils.AssertUtil;
import cn.tpshion.vm.domain.entity.Secret;
import cn.tpshion.vm.domain.entity.table.SecretTableDef;
import cn.tpshion.vm.domain.support.GitData;
import cn.tpshion.vm.mapper.SecretMapper;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.CreateBranchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class GitBranchHandle {

    @Resource
    private NodeConfig config;

    @Resource
    private SecretMapper secretMapper;

    public List<String> getBranchList(GitData data, String taskId) throws Exception{
        log.info("getBranchList data:{} taskId:{}", data, taskId);
        List<String> list = new ArrayList<>();
        Secret secret = getSecret(data.getSecretName());
        UsernamePasswordCredentialsProvider credentials = new UsernamePasswordCredentialsProvider(secret.getSecretKey(), secret.getSecretValue());

        String uri = data.getUrl();
        String name = uri.substring(uri.lastIndexOf("/") + 1, uri.lastIndexOf("."));
        String branch = StringUtils.hasText(data.getBranch()) ? data.getBranch() : data.getDefaultBranch();

        File file = new File(config.getWorkspace() + File.separator + taskId + File.separator + name);
        if(file.exists() && file.isDirectory()){

            try (Git git = new Git(new FileRepository(file.getPath() + "/.git"))) {
                git.checkout()
                        .setName(branch)
                        .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.SET_UPSTREAM)
                        .setStartPoint("origin/" + branch)
                        .setCreateBranch(false)
                        .setForced(true)
                        .call();

                git.pull().setCredentialsProvider(credentials).call();
                setBranchList(git, list);
            }
        }else{
            FileUtils.deleteDirectory(file);
            try (Git git = Git.cloneRepository()
                    .setURI(data.getUrl())
                    .setBranch(branch)
                    .setDirectory(file)
                    .setCredentialsProvider(credentials)
                    .call()) {

                setBranchList(git, list);
            }
        }

        return list;
    }

    private void setBranchList(Git git, List<String> list) throws Exception{
        ListBranchCommand branchList = git.branchList();
        List<Ref> refList = branchList.setListMode(ListBranchCommand.ListMode.ALL).call();
        for (Ref ref : refList) {
            log.info("getBranchList branch:{} name:{}", ref.getName(), ref.getObjectId().getName());
            if(StringUtils.startsWithIgnoreCase(ref.getName(), "refs/remotes/origin/")){
                list.add(ref.getName().replace("refs/remotes/origin/",""));
            }
        }
    }

    private Secret getSecret(String name){
        QueryWrapper queryWrapper = QueryWrapper.create().where(
                SecretTableDef.SECRET.TYPE.eq(SecretType.GIT).and(SecretTableDef.SECRET.NAME.eq(name))
        );
        Secret secret = secretMapper.selectOneByQuery(queryWrapper);
        AssertUtil.isEmpty(secret, "密钥获取失败");
        secret.setSecretKey(AESUtil.decrypt(secret.getSecretKey(), config.getSecret()));
        secret.setSecretValue(AESUtil.decrypt(secret.getSecretValue(), config.getSecret()));
        return secret;
    }
}
